<!DOCTYPE html>
<html>
<head>
<title>Selection canonicalization test</title>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<script>
description('Ranges/Nodes set by a Selection method and returned by a corresoponding Selection method should be identical.');

var sandboxRoot = document.createElement('div');
sandboxRoot.innerHTML =
    '<div id="non-editable-root"><span>A</span><span></span><span>B</span></div>' +
    '<div id="editable-root" contentEditable="true"><span>C</span><span></span><span>D</span></div>';
document.body.appendChild(sandboxRoot);

var selection = window.getSelection();

function selectRange(range)
{
    selection.removeAllRanges();
    selection.addRange(range);
}

function collapsedRangeAt(anchorNode, offset)
{
    var range = new Range();
    range.setEnd(anchorNode, offset);
    range.collapse();
    return range;
}

var originalRange;
var gotRange;

function testAddRange()
{
    originalRange = collapsedRangeAt(originalAnchorNode, originalAnchorOffset);
    selectRange(originalRange);
    gotRange = selection.getRangeAt(0);

    shouldBeTrue('gotRange.startContainer === originalRange.startContainer');
    shouldBe('gotRange.startOffset', 'originalRange.startOffset');
    shouldBeTrue('gotRange.endContainer === originalRange.endContainer');
    shouldBe('gotRange.endOffset', 'originalRange.endOffset');
}

function testCollapse()
{
    selection.collapse(originalAnchorNode, originalAnchorOffset);
    gotRange = selection.getRangeAt(0);
    shouldBeTrue('gotRange.startContainer === originalAnchorNode');
    shouldBe('gotRange.startOffset', 'originalAnchorOffset');
    shouldBeTrue('gotRange.endContainer === originalAnchorNode');
    shouldBe('gotRange.endOffset', 'originalAnchorOffset');
}

var originalAnchorNode;
var originalAnchorOffset;
function testSingleRange(anchorNode, anchorOffset)
{
    originalAnchorNode = anchorNode;
    originalAnchorOffset = anchorOffset;

    testAddRange();
    testCollapse();
}

function runTest(rootElement)
{
    var span1 = rootElement.childNodes[0];
    var span2 = rootElement.childNodes[1];
    var span3 = rootElement.childNodes[2];
    var text1 = span1.firstChild;
    var text2 = span3.firstChild;

    // These positions are all visually equivalent, and should not mutate when obtained by getRangeAt().
    debug('position = [text1, 1]');
    testSingleRange(text1, 1);
    debug('position = [span1, 1]');
    testSingleRange(span1, 1);
    debug('position = [rootElement, 1]');
    testSingleRange(rootElement, 1);
    debug('position = [span2, 0]');
    testSingleRange(span2, 0);
    debug('position = [rootElement, 2]');
    testSingleRange(rootElement, 2);
    debug('position = [span3, 0]');
    testSingleRange(span3, 0);
    debug('position = [text2, 0]');
    testSingleRange(text2, 0);
}

debug('Testing selection on non-editable nodes...');
runTest(document.getElementById('non-editable-root'));
debug('Testing selection on editable nodes...');
runTest(document.getElementById('editable-root'));

document.body.removeChild(sandboxRoot);
</script>
</body>
</html>
